package com.zimo.download.info.event;

import com.zimo.download.info.ServerFileINFO;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Objects;

/**
 * 事件集合
 * 为了方便管理和使用事件的一个集合，他不支持 EventHandler 的事件处理程序，只支持最新的EventHandlerS事件处理程序
 * 该类是通过 事件类型 和 文件名称 共同构成的一个事件ID，来管理事件的
 *
 * 添加事件 使用addEvent***方法
 * 删除事件 使用removeEvent***方法
 *
 * 如果你打算开发一个下载器并且用来响应事件那么请使用 getEvent*** 方法来获取事件对象，获取之后你就调用你获取的对象里面唯一的方法来响应这个事件
 */


public class EventSet {

    //事件ID全局唯一，并且事件由事件ID前面的前缀来区分事件类型(由事件类型与事件名称共同组成一个事件ID)
    private HashMap <EventID, EventHandlerS> eventIDs = new HashMap<>();//存放事件ID

    private static EventSet eventSet;
    private EventSet (){}
    public static synchronized EventSet getEventSet() {
        if (eventSet == null) {
            eventSet = new EventSet();
        }
        return eventSet;
    }



/****************************************************************   内部类 EventID    ************************************************************************************/

    /**
     * 事件ID内部类
     * 重写了，toString 和 equals方法，为了让EventID 对象在HashMap里唯一
     */

    private class EventID{
        private String ID;
        public EventID(String eventType,String fileName){
            this.ID=eventType+fileName;
        }
        public String getID() {
            return ID;
        }

        @Override
        public String toString() {
            return ID;
        }

        /**
         * 重写equals 让HashSet对比两个ID是否一样时不再对比地址值，转而对比ID
         * @param o
         * @return
         */
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            EventID eventID = (EventID) o;
            return Objects.equals(ID, eventID.ID);
        }

        /**
         * 重写 hashCode 计算ID的散列码而不是计算EventID对象的散列码
         */
        @Override
        public int hashCode() {
            return Objects.hash(ID);
        }
    }


/****************************************************************   添加监听事件    ************************************************************************************/


    public void addEvent(EventID id,EventHandlerS eventHandler){
        eventIDs.put(id, eventHandler);
    }

    /**
     * 监听下载速度
     * @param url
     * @param event
     */
    public void addEventSpeed(URL url,EventSpeed event){
        try {
            addEvent(new EventID(Event.Speed,ServerFileINFO.getFileName(url)),event);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 监听线程下载完成事件
     * @param url
     * @param event
     */
     public void addEventFinish(URL url,EventFinish event) {
         try {
             addEvent(new EventID(Event.DownloadedFinish,ServerFileINFO.getFileName(url)),event);
         } catch (IOException e) {
             e.printStackTrace();
         }

     }

    /**
     * 监听线程暂停事件
     * @param url
     * @param event
     */
     public void addEventStop(URL url,EventHandlerS event){
         try {
             addEvent(new EventID(Event.StopThreadName,ServerFileINFO.getFileName(url)),event);
         } catch (IOException e) {
             e.printStackTrace();
         }
     }

/****************************************************************   获取事件对象方法    ************************************************************************************/

    /**
     * 获取事件对象，通过事件类型 和 文件名称组成的唯一ID获取
     * @param id
     * @return
     */
    private EventHandlerS getEvent(EventID id){
        return eventIDs.get(id);
    }


    /**
     * 获取线程速度事件对象
     * @param url
     * @return
     */
     public EventHandlerS getEventSpeed(URL url){
         try {
            return getEvent(new EventID(Event.Speed , ServerFileINFO.getFileName(url)));
         } catch (IOException e) {
             e.printStackTrace();
         }
         return null;
     }

    /**
     * 获取线程下载完成事件对象
     * @param url
     * @return
     */
     public EventHandlerS getEventFinish(URL url){
         try {
             return getEvent(new EventID(Event.DownloadedFinish , ServerFileINFO.getFileName(url)));
         } catch (IOException e) {
             e.printStackTrace();
         }
         return null;
     }

     /**
     * 获取线程暂停事件对象
     * @param url
     * @return
     */
     public EventHandlerS getEventStop(URL url){
         try {
             return getEvent(new EventID(Event.StopThreadName , ServerFileINFO.getFileName(url)));
         } catch (IOException e) {
             e.printStackTrace();
         }
         return null;
     }

/****************************************************************   获取事件对象方法    ************************************************************************************/

    /**
     * 删除该ID的事件 remove类方法的模板
     * @param id
     * @return
     */
    private EventHandlerS remove(EventID id){
        return eventIDs.remove(id);
    }

    /**
     * 删除该URL下的所有事件
     * @param url
     * @return
     */
    public boolean remove(URL url) throws IOException {
        removeEventSpeed(url);
        removeEventFinish(url);
        return true;
    }

    public  EventHandlerS removeEventSpeed(URL url) throws IOException {
        return remove(new EventID(Event.Speed,ServerFileINFO.getFileName(url)));
    }

    public  EventHandlerS removeEventFinish(URL url) throws IOException {
        return remove(new EventID(Event.DownloadedFinish,ServerFileINFO.getFileName(url)));
    }






}
